package socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 服务端
 */
public class Server {

    //private List<PrintWriter> allOut = new ArrayList<>();
    private Map<String,PrintWriter> allOut = new HashMap<>();//key:客户端昵称，value:昵称对应的输出流
    private ServerSocket serverSocket;

    public Server() {
        System.out.println("正在启动服务器...");
        try {
            serverSocket = new ServerSocket(8080);
            System.out.println("服务器启动完毕");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 启动程序执行
     */
    public void start() {
        System.out.println("等待客户端连接...");
        try {
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端连接了");

                /*InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);
                String line;
                while((line=br.readLine())!=null){
                    System.out.println("客户端："+line);
                }*/
                Runnable handler = new ClientHandler(socket);
                Thread thread = new Thread(handler);
                thread.start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }

    private class ClientHandler implements Runnable {
        private Socket socket;
        private String host;//记录客户端的地址信息
        private String nickname;//记录客户端的昵称

        public ClientHandler(Socket socket) {
            this.socket = socket;
            host = socket.getInetAddress().getHostAddress();
        }

        public void run() {
            PrintWriter pw = null;
            try {
                InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);
                nickname = br.readLine();



                OutputStream out = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
                BufferedWriter bw = new BufferedWriter(osw);
                pw = new PrintWriter(bw, true);

                /*if(allOut.containsKey(nickname)){
                    pw.println("该昵称已存在，请重新输入！");
                }*/

                //将对应客户端的输出流存入到共享集合allOut中
                synchronized (allOut) {//同步监视器对象选取临界资源
                    allOut.put(nickname,pw);
                }
                broadcast(nickname + "[" + host + "]" + "上线了，当前在线人数：" + allOut.size());

                String line;
                while ((line = br.readLine()) != null) {
                    if(line.startsWith("@")){
                        //执行私聊方法
                        sendMessageToSomeone(line);
                    }else{
                        broadcast(host + "说：" + line);
                    }

                }
            } catch (IOException e) {

            } finally {
                //处理该客户端断开连接后的操作
                synchronized (allOut) {
                    //allOut.remove(pw);
                    allOut.remove(nickname);
                }
                broadcast(nickname + "[" + host + "]" + "下线了，当前在线人数" + allOut.size());
                try {
                    socket.close();//四次挥手
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void broadcast(String message) {
            System.out.println(message);
            synchronized (allOut) {
                for (PrintWriter o : allOut.values()) {//遍历集合的过程中不允许向集合中增删元素
                    o.println(message);
                }
            }
        }
        private void sendMessageToSomeone(String message){
            if(message.matches("@.+:.+")) {
                String toNickname = message.substring(1, message.indexOf(":"));

                if(allOut.containsKey(toNickname)){
                    PrintWriter sendToSomeone = allOut.get(toNickname);
                    String message_s = message.substring(message.indexOf(":") + 1);
                    sendToSomeone.println("来自" + nickname + "私信:" + message_s);
                }else{
                    PrintWriter sendToMe = allOut.get(nickname);
                    sendToMe.println("该用户不存在");
                }

            }else{
                PrintWriter sendToMe = allOut.get(nickname);
                sendToMe.println("私聊格式不正确");
            }



        }
    }
}
